home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Commodore Free 13
/
Commodore_Free_Issue_13_2007_Commodore_Computer_Club.d64
/
t.hex files 8
< prev
next >
Wrap
File List
|
2023-02-26
|
11KB
|
360 lines
uHexFiles part 8
By Jason Kelk
http://www.oldschool-gaming.com
Okay, so last issue we were looking at
$D018 & how it controls where our
screen & character set data are held in
the C64's memory & most of you (I hope)
will have noticed that the highest
place I said we could put a font was
$3800 & the highest place for a screen
$3C00, yes? Simiarly, because sprite
data pointers can only have a maximum
value of $FF & each sprite is $40 bytes
long, the last sprite is at $3FC0. This
is because, the VIC-II chip arranges
memory into four chunks of 16K. On
powerup, the C64 is pointing to video
bank 0, which runs from $0000 to $3FFF,
& at the screen at $0400 & a font at
$1000. This, incidentally, is why our
examples have all had music sitting at
$1000, the VIC-II can't 'see' this RAM
under there for sprites, characters or
screen data because a copy of the ROM
character set is there, $1000 to $17FF
for the upper case font & $1800 to
$2000 for the lower.
The easiest way to imagine it is with 2
pieces of paper. The first has a piece
of code written on it & is placed on a
desk whilst the second has a picture
drawn on it & is held a small distance
above the first. We, pretending to be
the processor here, can look at the 1st
piece of paper by putting our head
underneath the second, but the VIC-II
looks straight down & from this angle
the first is totally obscured. This
technique is called 'shadowing' and,
although it appears to be adding a
limitation to how we use memory, it
actually makes life easier for us in
that we can still actually use the
memory in some way rather than it being
locked off for the characters. We'll
come across more examples of shadowing
in a different form in a later article.
But back to our initial line of
thought, how can we use one of the
other three blocks of 16K for our
graphics? After all, if we use a bitmap
picture (more on those a little later)
we need about 9K of space for it,
there is only a limited space in bank
0, what with $0000 to $0400 & $1000 to
$2000 being unavailable to us.
This is where $DD00 comes in to play.
One of $DD00's jobs is handling this
very problem, the lowest two bits are
used to point VIC-II at the correct
place. If we just put a value of $03
into $DD00 nothing happens because,
oddly, $DD00 actually refers to the
first bank as $03 & the last as $00. So
if we want to use bank 1 ($4000-$7FFF)
we can do so by setting $DD00 with $02.
Changing into bank 1 is the equivilent
of adding $4000 (16384) to all of our
character, screen 6 sprite data
pointers. If we just change into bank 1
with no other changes made to the
VIC-II we end up looking at a screen at
$4400 & a font at $5000. Since there is
no shadow of the ROM font in bank 1
that means we just see a mess. And more
importantly, we have the entire 16K to
ourselves! And simliar rules apply to
banks 2 & 3, except that bank 2 starts
at $8000 & has a second copy of the ROM
font at $9000 to $9FFF & bank 3 starts
at $C000 and has the video chip sitting
at $D000 to $E000. We can write to this
memory, but it requires a little
trickery and, since using it is a lot
more complex, I won't cover this until
later. But bank 1 is the most commonly
used bank for graphics since it's all
ours with absolutely no strings
attached by the C64, so for now we're
going to frolic in this new pasture &
not worry about the rest.
Now we've got a play space, time to
introduce something new to fill it with
in the form of bitmaps. Remember I
mentioned them last time as well?
Right, first off, there are a number of
different editors out there, all with
different memory layouts. During the
planning for these articles, there was
some discussion about which would be
best to use for our purposes & we've
decided to use the format set down by
the editor Vidcom. In general a bitmap
is split into two parts, the actual
picture (which is 8,000 bytes of data,
since 40 characters across times 25
down times 8 bytes a character comes to
8,000) and we're only allowed to put
this in either $4000 or $6000 in this
bank (and the same rule applies to the
other banks, the bitmap can only start
at a multiple of $2000).
The second part is the colors, with a
monocolor bitmap we get two colors
every 8x8 pixel square of the picture &
these can be represented by the two
halves of a byte; $F4 for example will
be light grey ($F) & purple ($4). This
means we need 1,000 bytes of color for
a monocolor bitmap. Multicolor is
different, we get the same system for
defining 2 of the colours, but the
$D800 colour map is also available as
is the background colour, since multi-
color bitmaps work in the same way as
multicolor characters with two bits
working together to make a color value
of $0 to $3. This means we need a total
2,000 bytes of color data, one for the
screen & the other for $D800. Vidcom
arranges its files like this:
$5800 to $5BE7 - color data for $D800
onwards.
$5C00 to $5FE7 - color data for
wherever the screen is.
$6000 to $7F3F - bitmap.
We're going to take advantage of this.
Because any of the sixteen screens in
bank 1 can be used as our screen we're
not going to bother copying the data
from $5C00 to $5FE7, oh no. We're going
to tell the VIC-II to look there for
it's screen, & by a coincidence... oh
look, here's our color data! Now, if
you download & unzip the sample data
there is an example picture included
called tropique.prg & a piece of source
that I want you to open called
pic_show.asm. It should look like this:
.incbin tropique.prg
*= $0900
; Black border & screen colors
lda #$00
sta $d020
sta $d021
; Set VIC-II to bank 1
lda #$02
sta $dd00
; Turn on bitmap mode
lda #$3b
sta $d011
; Turn on multicolor mode
lda #$18
sta $d016
; Point the screen at $5C00 & the font
at $6000
lda #$78
sta $d018
; Copy from $5800-$5BE7 to $D800-$dBE7
ldx #$00
copycol lda $5800,x
sta $d800,x
lda $5900,x
sta $d900,x
lda $5a00,x
sta $da00,x
lda $5ae8,x
sta $dae8,x
inx
bne copycol
; Stop but don't exit to BASIC
loop jmp loop
Start it up & if it's typed correctly,
a nice picture of a girl & some stone
columns should appear! There's also a
file in the archive called pic_demo.asm
and, as the filename might suggest,
this is a demo based on the previous
code we've looked at & the picture
viewer. This source isn't documented,
but the majority of it is code we've
already covered quite extensively so
you should feel pretty comfortable with
it - but there have been a few alter-
ations made so they need a little
explanation; one change makes the
scroller faster & therefore more read-
able, the other extends the length of
the message itself so it's no longer
limited to 256 bytes.
Lets look at how the scroll is sped up
first; open the pic_show.asm source &
look for the label scrlloop it should
be line 127) & there is an LDY #$00
just before it; since the Y register
isn't used during the scroll movement
routine, it's being put to service as a
counter to call that code more than
once per frame. If you page onwards a
little to the label dontmove, here's
this;
iny
cpy #$03
bne scrlloop
And that's what speeds the scroller up;
the routine is called, Y gets increm-
ented & we go back to scrlloop until Y
reaches 3. Changing the value can speed
up or slow down the scroller accord-
ingly, so it's worth having a little
play to see how it looks, on average
moving two to three pixels a frame
tends to be readable when the text is
the size we're using here.
The other modification is a little more
involved & before I start explaining
how it works a little disclaimer is
probably in order; the technique below
is called 'self modifying code' & is,
generally speaking, considered bad
practice by just about every prog-
ramming course, teacher & book.
However, it's very effective & faster
to use most of the time & since I use
it personally in preference to the more
fiddly 'proper' methods, it's covered
here.
Previously, we've been using a label
called messcount to indicate where we
are in the text, that has been totally
removed for this code. Instead we have
this routine after the loop to shift
all the characters to the left:
messread lda message
bne textok
jsr reset
jmp messread
textok sta $5c27
inc messread+$01
bne nohibyte
inc messread+$02
So, looking at this new routine it
reads from the label message (which is
where the scroll text is stored, at
$2800 in memory for this code), checks
it's not a value of $00 & puts the new
character on the screen. If the accum-
ulator does contain $00, a subroutine
called reset is called & the code jumps
back to the LDA to get another byte.
Now, some of you are thinking 'hang on,
that just reads the same byte over &
over again' & on it's own you'd be
right, the two INC commands after
textok are what nudges the LDA on so it
reads the text.
How does that work, then? Well, if we
look into memory where the LDA message
is stored, it will look like this; $AD,
$00, $28. The first byte $AD is the
actual LDA command, while the second &
third bytes are the address, in this
case pointing to $2800 since the C64
insists on storing the lower byte of
the address first. The two INCs change
the address, the first one changes the
lower byte (the one that starts as $00
in this case) upwards so the LDA itself
steps through memory a byte at a time,
while the second INC only takes effect
at the point when that byte reaches $00
again; it bumps the higher byte of the
address up so the scroller can go from
$28ff to $2900. Finally, we need a look
at reset (near the end of the code) as
well:
reset lda #message
sta messread+$02
rts
This subroutine simply resets messread
so that it points to the first byte of
the text, the first LDA/STA pair sets
the lower byte of the address, the
second LDA/STA sets the higher, so the
code at messread gets changed to $AD,
$00, $28 regardless of what it was
previously.
This subroutine is also called a little
before the CLI in the setup code to
make sure that the program behaves if
someone stops & restarts it. Without
that call in the setup the text would
continue where it left off!
Have fun playing with the code,
changing the speed of the scroller & so
forth & generally seeing how things
work. For the next installment we're
going to start a whole new project. As
usual, if you have any questions,
contact me & I'll see what I can do
but, for now, goodbye!
The source code for the routines above
can be downloaded at:
www.oldschool-gaming.com/files/c64/
hex_files/part_8_files.zip
Commodore Free would like to thank
Jason for permitting the reprinting of
the article